﻿#include "EditorMainWindowView.h"
#include "EditorMainWindowViewModel.h"

#include "Framework/Editor.h"

#include "Widgets/Window.h"
#include "Widgets/RectangleWidget.h"
#include "Widgets/Mouse/MouseWidget.h"
#include "Widgets/ImageWidget.h"
#include "Widgets/Positioners/HorizontalPositionerWidget.h"
#include "Widgets/Positioners/VerticalPositionerWidget.h"
#include "Widgets/Positioners/FunctionPositionerWidget.h"
#include "Widgets/RectangleWidget.h"
#include "Widgets/TextWidget.h"

#include "Widgets/EditorImageButton.h"
#include "Widgets/Splitable/EditorSplitableLayoutView.h"

#include "WindowEnums.h"
#include "Math/Math.h"
#include "Output/Console.h"

#include "Ability/Explorer/EditorExplorerAbilityGroupViewModel.h"
#include "Ability/Explorer/EditorExplorerAbilityGroupView.h"
#include "Ability/DebugAndRun/EditorDebugAndRunAbilityGroupViewModel.h"
#include "Ability/DebugAndRun/EditorDebugAndRunAbilityGroupView.h"

#include "PageArea/EditorPageAreaManagerView.h"
#include "AbilityGroup/SideBar/EditorSideBarView.h"
#include "AbilityGroup/SideBar/EditorSideBarViewModel.h"
#include "AbilityGroup/Panel/EditorPanelView.h"
#include "StatusBar/EditorStatusBarView.h"
#include "Notification/EditorNotificationView.h"
#include "Menubar/EditorMenuBarView.h"

#include "Framework/Editor.h"
#include "Theme/EditorTheme.h"


REditorMainWindowView::REditorMainWindowView()
{
}

void REditorMainWindowView::BindViewModel(TSharedObjectPtr<REditorWindowViewModel> InViewModel)
{
    Super::BindViewModel(InViewModel);
    ViewModel = InViewModel;

    MainSideBar=NewObject<REditorSideBarView>(this);
    MainSideBar->BindViewModel(ViewModel->GetMainSideBar());

    SecondarySideBar=NewObject<REditorSideBarView>(this);
    SecondarySideBar->BindViewModel(ViewModel->GetSecondarySideBar());

    PanelView=NewObject<REditorPanelView>(this);
    PanelView->OnHidePanel.Bind(
        [this](){
            this->ViewModel->HidePanel();
        }
    );

    PanelView->BindViewModel(ViewModel->GetPanel());

    BodyLayout=NewObject<REditorSplitableLayoutView>(this);
    BodyLayout->OnBindItemView.BindLambda(
        [this](RObjectPtr InItemModel)->RObjectPtr
        {
            if(InItemModel==ViewModel->GetMainSideBar())
            {
                return MainSideBar;
            }
            else if(InItemModel==ViewModel->GetSecondarySideBar())
            {
                return SecondarySideBar;
            }
            else if(InItemModel==ViewModel->GetPanel())
            {
                return PanelView;
            }
            else if(InItemModel==ViewModel->GetPageArea())
            {
                return GetPageArea();
            }
            else
            {
                assert(false);
                return nullptr;
            }
        }
    );
    BodyLayout->OnFillItemWidget.BindLambda(
        [this](RObjectPtr InItemView, RWidgetPtr InParentWidget)
        {
            if(InItemView==MainSideBar)
            {
                MainSideBar->FillWidget(InParentWidget);
            }
            else if(InItemView==SecondarySideBar)
            {
                SecondarySideBar->FillWidget(InParentWidget);
            }
            else if(InItemView==PanelView)
            {
                PanelView->FillWidget(InParentWidget);
            }
            else if(InItemView==GetPageArea())
            {
                GetPageArea()->CreateWidget(InParentWidget);
            }
            else
            {
                assert(false);
            }
        }
    );

    BodyLayout->BindViewModel(ViewModel->GetBodyLayout());

    StatusBarView=NewObject<REditorStatusBarView>(this);
    StatusBarView->BindViewModel(ViewModel->GetStatusBar());

    NotificationView=NewObject<REditorNotificationView>(this);
    NotificationView->BindViewModel(ViewModel->GetNotification());

    MenuBarView=NewObject<REditorMenuBarView>(this);
    MenuBarView->BindViewModel(ViewModel->GetMenuBar());

    CreateAndShowWindow();
    FillWindow();
}


void REditorMainWindowView::FillWindow()
{
    RWindowWeakPtr WindowWeakPtr=Window;


    auto WindowMenu=NewWidget<RWidget>(WindowWeakPtr->GetRootWidget());
    WindowMenu->Height=ViewModel->TitleBarHeight;
    WindowMenu->X=ViewModel->MenuLeftMargin;
    WindowMenu->Width=ViewModel->MenuWidth;
    FillMenuWidgets(WindowMenu);

    //a  of button to control window layout
    //such as shhow/hide side bar
    auto LayoutControlButtons=NewWidget<RHorizontalPositionerWidget>(WindowWeakPtr->GetRootWidget());
    {
        LayoutControlButtons->Anchor.RightReference=WindowButtonsWidget;
        LayoutControlButtons->Anchor.RightReferenceEdge=EHorizontalWidgetEdge::Left;
        LayoutControlButtons->Height=ViewModel->TitleBarHeight;
        LayoutControlButtons->Width=ViewModel->LayoutControlButtonSize*3+ViewModel->LayoutControlButtonPadding*2;
        LayoutControlButtons->Spacing=ViewModel->LayoutControlButtonPadding;

        auto MainSideBarToggleButton=NewWidget<RMouseWidget>(LayoutControlButtons);
        MainSideBarToggleButton->Width=ViewModel->LayoutControlButtonSize;
        MainSideBarToggleButton->Height=ViewModel->LayoutControlButtonSize;
        MainSideBarToggleButton->Anchor.VerticalCenterReference=LayoutControlButtons;
        MainSideBarToggleButton->OnClicked.BindLambda([this](const SMouseButtonEvent&){
            this->ViewModel->ToggleMainSideBar();
            return true;
        });

        RMouseWidgetWeakPtr MainSideBarToggleButtonWeakPtr=MainSideBarToggleButton;

        auto MainSideBarToggleBackground=NewWidget<RRectangleWidget>(MainSideBarToggleButton);
        MainSideBarToggleBackground->FillColor=ViewModel->LayoutControlButtonBackgroundColor;
        MainSideBarToggleBackground->Radius=ViewModel->LayoutControlButtonRadius;
        MainSideBarToggleBackground->Anchor.Fill(MainSideBarToggleButton);
        MainSideBarToggleBackground->Fill=[MainSideBarToggleButtonWeakPtr]()->bool{
            return MainSideBarToggleButtonWeakPtr->IsHovered();
        };

        auto MainSideBarToggleButtonImage=NewWidget<RImageWidget>(MainSideBarToggleButton);
        MainSideBarToggleButtonImage->Width=ViewModel->LayoutControlButtonImageSize;
        MainSideBarToggleButtonImage->Height=ViewModel->LayoutControlButtonImageSize;
        MainSideBarToggleButtonImage->Anchor.CenterIn(MainSideBarToggleButton);
        MainSideBarToggleButtonImage->Image=[this]()
        {
            return ViewModel->GetMainSideBarToggleButtonImage();
        };


        auto PanelToggleButton=NewWidget<RMouseWidget>(LayoutControlButtons);
        PanelToggleButton->Width=ViewModel->LayoutControlButtonSize;
        PanelToggleButton->Height=ViewModel->LayoutControlButtonSize;
        PanelToggleButton->Anchor.VerticalCenterReference=LayoutControlButtons;
        PanelToggleButton->OnClicked.BindLambda([this](const SMouseButtonEvent&){
            this->ViewModel->TogglePanel();
            return true;
        });
        RMouseWidgetWeakPtr PanelToggleButtonWeakPtr=PanelToggleButton;

        auto PanelToggleBackground=NewWidget<RRectangleWidget>(PanelToggleButton);
        PanelToggleBackground->FillColor=ViewModel->LayoutControlButtonBackgroundColor;
        PanelToggleBackground->Radius=ViewModel->LayoutControlButtonRadius;
        PanelToggleBackground->Anchor.Fill(PanelToggleButton);
        PanelToggleBackground->Fill=[PanelToggleButtonWeakPtr]()->bool{
            return PanelToggleButtonWeakPtr->IsHovered();
        };

        auto PanelToggleButtonImage=NewWidget<RImageWidget>(PanelToggleButton);
        PanelToggleButtonImage->Width=ViewModel->LayoutControlButtonImageSize;
        PanelToggleButtonImage->Height=ViewModel->LayoutControlButtonImageSize;
        PanelToggleButtonImage->Anchor.CenterIn(PanelToggleButton);
        PanelToggleButtonImage->Image=[this]()
        {
            return ViewModel->GetPanelToggleButtonImage();
        };

        auto SecondarySideBarToggleButton=NewWidget<RMouseWidget>(LayoutControlButtons);
        SecondarySideBarToggleButton->Width=ViewModel->LayoutControlButtonSize;
        SecondarySideBarToggleButton->Height=ViewModel->LayoutControlButtonSize;
        SecondarySideBarToggleButton->Anchor.VerticalCenterReference=LayoutControlButtons;
        SecondarySideBarToggleButton->OnClicked.BindLambda([this](const SMouseButtonEvent&){
            this->ViewModel->ToggleSecondarySideBar();
            return true;
        });

        RMouseWidgetWeakPtr SecondarySideBarToggleButtonWeakPtr=SecondarySideBarToggleButton;

        auto SecondarySideBarToggleBackground=NewWidget<RRectangleWidget>(SecondarySideBarToggleButton);
        SecondarySideBarToggleBackground->FillColor=ViewModel->LayoutControlButtonBackgroundColor;
        SecondarySideBarToggleBackground->Radius=ViewModel->LayoutControlButtonRadius;
        SecondarySideBarToggleBackground->Anchor.Fill(SecondarySideBarToggleButton);
        SecondarySideBarToggleBackground->Fill=[SecondarySideBarToggleButtonWeakPtr]()->bool{
            return SecondarySideBarToggleButtonWeakPtr->IsHovered();
        };

        auto SecondarySideBarToggleButtonImage=NewWidget<RImageWidget>(SecondarySideBarToggleButton);
        SecondarySideBarToggleButtonImage->Width=ViewModel->LayoutControlButtonImageSize;
        SecondarySideBarToggleButtonImage->Height=ViewModel->LayoutControlButtonImageSize;
        SecondarySideBarToggleButtonImage->Anchor.CenterIn(SecondarySideBarToggleButton);
        SecondarySideBarToggleButtonImage->Image=[this]()
        {
            return ViewModel->GetSecondarySideBarToggleButtonImage();
        };
    }

    //body do not contain top and bottom spliter
    FillWindowBodyWidgets();


    auto StatusBar=NewWidget<RWidget>(WindowWeakPtr->GetRootWidget());
    StatusBar->Anchor.HorizontalFill(WindowWeakPtr->GetRootWidget());
    StatusBar->Anchor.BottomReference=WindowWeakPtr->GetRootWidget();
    StatusBar->Height=ViewModel->StatusBarHeight;
    StatusBarView->FillWidgets(StatusBar);

    //通知控件
    NotificationView->FillWidgets(WindowWeakPtr->GetRootWidget());

}

void REditorMainWindowView::FillWindowBodyWidgets()
{
    auto Body=NewWidget<RWidget>(WindowContentWidget);
    Body->Anchor.Fill(WindowContentWidget);

    auto ActivityBarShared=NewWidget<RWidget>(Body);
    ActivityBarShared->Anchor.VerticalFill(Body);
    ActivityBarShared->Width=ViewModel->ActivityBarWidth;
    FillActivityBarWidgets(ActivityBarShared);

    auto BodyLayoutWidget=NewWidget<RWidget>(Body);
    BodyLayoutWidget->Anchor.VerticalFill(Body);
    BodyLayoutWidget->Anchor.RightReference=Body;
    BodyLayoutWidget->Anchor.LeftReference=ActivityBarShared;
    BodyLayoutWidget->Anchor.LeftReferenceEdge=EHorizontalWidgetEdge::Right;

    BodyLayout->CreateWidget(BodyLayoutWidget);
    return;
}

void REditorMainWindowView::FillMenuWidgets(TSharedObjectPtr<RWidget> InMenuWidget)
{
    MenuBarView->FillMenuWidgets(InMenuWidget);
}

void REditorMainWindowView::FillActivityBarWidgets(TSharedObjectPtr<RWidget> InActivityBarWidget)
{
    //InActivityBarWidget->bClipSubWidgets=true;
    auto Background=NewWidget<RRectangleWidget>(InActivityBarWidget);
    Background->Anchor.Fill(InActivityBarWidget);
    Background->FillColor=REditor::Get()->CurrentTheme->BackgroundColor;

    //paint ability s
    auto AbilityTabs=NewWidget<RVerticalPositionerWidget>(InActivityBarWidget);
    AbilityTabs->Anchor.HorizontalFill(InActivityBarWidget);
    AbilityTabs->Y=0;
    AbilityTabs->Height=[this](){
        return this->ViewModel->GetActivityAbilityTabsHeight();
    };

    for(int64_t Index=0; Index<ViewModel->GetActivityAbilityTabsCount(); ++Index)
    {
        auto Tab=NewWidget<RWidget>(AbilityTabs);
        Tab->Height=ViewModel->ActivityButtonHeight;
        Tab->Anchor.HorizontalFill(AbilityTabs);

        auto TabMouseWidget=NewWidget<RMouseWidget>(Tab);
        TabMouseWidget->Anchor.Fill(Tab);
        TabMouseWidget->OnClicked.BindLambda([this,Index](const SMouseButtonEvent&){
            this->ViewModel->OnActivityBarTabClicked(Index);
            return true;
        });
        TabMouseWidget->OnEntered.BindLambda([this,Index](){
            this->ViewModel->GetMainSideBar()->HoveredAbilityIndex=Index;
        });
        TabMouseWidget->OnExited.BindLambda([this,Index](){
            if(this->ViewModel->GetMainSideBar()->HoveredAbilityIndex==Index)
            {
                this->ViewModel->GetMainSideBar()->HoveredAbilityIndex=-1;
            }
        });

        auto Highlight=NewWidget<RRectangleWidget>(Tab);
        Highlight->Anchor.VerticalFill(Tab);
        Highlight->Width=ViewModel->ActivityButtonHighlightWidth;
        Highlight->FillColor=ViewModel->ActivityButtonHighlightColor;
        Highlight->Visible=[this,Index](){
            return this->ViewModel->IsActivityBarTabHighlight(Index);
        };

        auto Icon=NewWidget<RImageWidget>(Tab);
        Icon->Anchor.CenterIn(Tab);
        Icon->Width=ViewModel->ActivityButtonImageSize;
        Icon->Height=ViewModel->ActivityButtonImageSize;
        Icon->Image=[this,Index](){
            return this->ViewModel->GetActivityAbilityTabIcon(Index);
        };

    }


}

void REditorMainWindowView::FillEditorAreaWidgets(TSharedObjectPtr<RWidget> InEditorAreaWidget)
{
    //InEditorAreaWidget->bClipSubWidgets=true;
    auto Background=NewWidget<RRectangleWidget>(InEditorAreaWidget);
    Background->Anchor.Fill(InEditorAreaWidget);
    Background->FillColor=REditor::Get()->CurrentTheme->BackgroundColor;
    PageAreaView->CreateWidget(Background);

}

